/* * Reference GTL Parser for Java * Copyright (c) 2000-2009 Constantine A Plotnikov * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package net.sf.etl.parsers.emf; import java.util.Collection; import java.util.HashMap; import net.sf.etl.parsers.LiteralUtils; import net.sf.etl.parsers.ObjectName; import net.sf.etl.parsers.ParserException; import net.sf.etl.parsers.TermParser; import net.sf.etl.parsers.TermToken; import net.sf.etl.parsers.Terms; import net.sf.etl.parsers.Token; import net.sf.etl.parsers.utils.AbstractTreeParser; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; /** * EMF term parser. * * @author const */ public class EMFTermParser extends AbstractTreeParser<EObject, EStructuralFeature, EClass, Collection<Object>> { /** a logger */ private static final java.util.logging.Logger log = java.util.logging.Logger .getLogger(EMFTermParser.class.getName()); /** A cache of types */ private final HashMap<ObjectName, EClass> typeCache = new HashMap<ObjectName, EClass>(); /** A cache of packages */ private final HashMap<String, EPackage> packageCache = new HashMap<String, EPackage>(); /** * A constructor * * @param parser * a term parser to use */ public EMFTermParser(TermParser parser) { super(parser); } /** * {@inheritDoc} */ @Override protected EObject createInstance(EClass metaObject, ObjectName name) { final EClass type = metaObject; return type.getEPackage().getEFactoryInstance().create(type); } /** * @see net.sf.etl.parsers.utils.AbstractTreeParser#getMetaObject(net.sf.etl.parsers.ObjectName) */ @Override protected EClass getMetaObject(ObjectName name) { EClass type = typeCache.get(name); if (type != null) { return type; } EPackage p = packageCache.get(name.namespace()); if (p == null) { p = EPackage.Registry.INSTANCE.getEPackage(name.namespace()); if (p == null) { log.severe("Namespace " + name.namespace() + " is not registered with parser. (at token " + parser.current() + ")"); throw new ParserException("Namespace " + name.namespace() + " is not registered with parser."); } packageCache.put(name.namespace(), p); } type = (EClass) p.getEClassifier(name.name()); if (type == null) { log.severe("Class " + name.name() + " not found in " + name.namespace()); throw new ParserException("Class " + name.name() + " not found in " + name.namespace()); } typeCache.put(name, type); return type; } @Override protected EStructuralFeature getPropertyMetaObject(EObject rc, EClass metaObject, TermToken token) { final EStructuralFeature f = getPropertyMetaObject(rc, metaObject, token.propertyName().name()); final boolean isList = parser.current().kind() == Terms.LIST_PROPERTY_START; if (isList != f.isMany()) { log.severe("Feature " + f.getName() + " in class " + f.getContainerClass().getName() + " has mismatch in multiplicity with grammar."); throw new ParserException("Feature " + f.getName() + " in class " + f.getContainerClass().getName() + " has mismatch in multiplicity with grammar."); } return f; } /** * {@inheritDoc} */ @Override protected void setToFeature(EObject rc, EStructuralFeature f, Object v) { final EObject o = rc; final EStructuralFeature ef = f; o.eSet(ef, v); } /** * {@inheritDoc} */ @Override protected void addToFeature(EObject rc, EStructuralFeature f, Collection<Object> holder, Object v) { final Collection<Object> l = holder; l.add(v); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") protected Collection<Object> startListCollection(EObject rc, EClass metaObject, EStructuralFeature f) { final EStructuralFeature ef = f; if (!ef.isMany()) { throw new ParserException("Feature is not of collection type: " + ef); } return (Collection<Object>) (rc).eGet(ef); } /** * {@inheritDoc} */ @Override protected void endListCollection(EObject rc, EClass metaObject, EStructuralFeature f, Collection<Object> holder) { // do nothing, collection has been updated in the progress } @Override protected EStructuralFeature getPropertyMetaObject(EObject rc, EClass metaObject, String name) { final EClass c = metaObject; final EStructuralFeature f = c.getEStructuralFeature(name); if (f == null) { log.severe("Feature " + name + " not found in " + c.getName() + " at " + parser.current()); throw new ParserException("Feature " + name + " not found in " + c.getName() + " at " + parser.current()); } return f; } /** * {@inheritDoc} */ @Override protected Object parseValue(EObject rc, EStructuralFeature f, Token value) { final EStructuralFeature field = f; final EClassifier type = field.getEType(); if (type instanceof EEnum) { return ((EEnum) type).getEEnumLiteral(value.text()).getInstance(); } else if (type instanceof EDataType) { final EDataType dt = (EDataType) type; final Class<?> c = dt.getInstanceClass(); if (c == int.class || c == Integer.class) { return new Integer(LiteralUtils.parseInt(value.text())); } else if (c == String.class) { return value.text(); } else { return dt.getEPackage().getEFactoryInstance().createFromString( dt, value.text()); } } else { throw new ParserException("Unsupported type for value: " + type); } } }